package cn.edu.xjtu.android.emoji_warfare_android.engine.entity;

import cn.edu.xjtu.android.emoji_warfare_android.engine.shape.Circle;
import cn.edu.xjtu.android.emoji_warfare_android.engine.shape.Rectangle;
import cn.edu.xjtu.android.emoji_warfare_android.engine.shape.Shape;

/**
 * CollideCheck类<br>
 * 碰撞检测类，该类是一个工具类。<br>
 * 用于判断两个实体是否有重叠部分，即是否碰撞。
 * 
 * @author bill
 *
 */
public class CollideCheck {
    /**
     * 检测两个实体是否碰撞(是否有重叠部分)
     * @param a 实体A
     * @param b 实体B
     * @return 碰撞返回真，否则返回假
     */
    public static boolean isOverlap(Entity a, Entity b) {
        Shape sa = a.outline;
        Shape sb = b.outline;
        if (sa instanceof Circle) {
            // sa为圆形
            if (sb instanceof Circle) {
                // sb为圆形
                return checkCircleCircle(a.basePoint, (Circle) sa, b.basePoint, (Circle) sb);
            } else if (sb instanceof Rectangle) {
                // sb为矩形
                return checkCircleRectangle(a.basePoint, (Circle) sa, b.basePoint, (Rectangle) sb);
            }
        } else if (sa instanceof Rectangle) {
            // sa为矩形
            if (sb instanceof Circle) {
                // sb为圆形
                return checkCircleRectangle(b.basePoint, (Circle) sb, a.basePoint, (Rectangle) sa);
            } else if (sb instanceof Rectangle) {
                // sb为矩形
                return checkRectangleRectangle(a.basePoint, (Rectangle) sa, b.basePoint, (Rectangle) sb);
            }
        }
        throw new IllegalArgumentException(String.format("Can't check overlap for shape %s and %s",
                sa.getClass().getName(), sb.getClass().getName()));
    }

    /**
     * 圆形和圆形碰撞检测。只要距离r &lt; 半径r1 + 半径r2 即为碰撞。
     */
    public static boolean checkCircleCircle(Point pa, Circle sa, Point pb, Circle sb) {
        float dx = pa.x - pb.x;
        float dy = pa.y - pb.y;
        float r = (float) Math.sqrt(dx * dx + dy * dy);
        return (r < sa.radius + sb.radius);
    }

    /**
     * 圆形和矩形碰撞检测。将长方向向外扩展半径r，形成一个大长方形，如果圆心在大长方形内，即为碰撞。
     */
    public static boolean checkCircleRectangle(Point pa, Circle sa, Point pb, Rectangle sb) {
        return (pa.x > pb.x + sb.x1 - sa.radius && pa.x < pb.x + sb.x2 + sa.radius && pa.y > pb.y + sb.y1 - sa.radius
                && pa.y < pb.y + sb.y2 + sa.radius);
    }

    /**
     * 矩形和矩形碰撞。计算出交叉区域的各个边界位置，如果能构成一个面积大于0的矩形，即为碰撞。
     */
    public static boolean checkRectangleRectangle(Point pa, Rectangle sa, Point pb, Rectangle sb) {
        float left = Math.max(pa.x + sa.x1, pb.x + sb.x1);
        float right = Math.min(pa.x + sa.x2, pb.x + sb.x2);
        float top = Math.max(pa.y + sa.y1, pb.y + sb.y1);
        float bottom = Math.min(pa.y + sa.y2, pb.y + sb.y2);
        return (left < right && top < bottom);
    }
}
